import {
  Directive,
  EventEmitter,
  Input,
  OnChanges,
  OnDestroy,
  OnInit,
  Output,
  SimpleChange
} from '@angular/core';

import { isNull } from '../helpers/object';

/*
import {
  toIcon,
  toMarkerOptions,
  toPoint,
  toSize
} from '../helpers/transformer';
*/

import { nullCheck } from '../helpers/validate';
import { MapService } from '../providers/mapService';
import { TMapInstance } from '../types/Map';
import { Marker, MarkerOptions } from '../types/Marker';
import { Point } from '../types/Point';
import { LngLat } from '../types/LngLat';
import { Label } from '../types/Label';
// import { LngLat } from '../types/Label';

@Directive({
  selector: 'marker'
})
export class MarkerDirective implements OnInit, OnChanges, OnDestroy {
  @Input() private point: LngLat;
  @Input() private options: MarkerOptions;
  @Input() private label: string;

  @Output() private loaded = new EventEmitter();
  @Output() private clicked = new EventEmitter();

  @Output() private dragstarted = new EventEmitter();
  @Output() private draged = new EventEmitter();
  @Output() private dragended = new EventEmitter();

  private marker: Marker;

  private _label: Label;

  constructor(private _service: MapService) {}

  public ngOnInit() {
    nullCheck(this.point, 'point is required for <marker>');

    this._service
      .addOverlay((map: TMapInstance) => {
        return (this.marker = new window.T.Marker(
          this.point,
          this.options
        ));
      })
      .then(({ map }) => {
        this.loaded.emit(this.marker);
        this.addListener(this.marker, map);
      })
      .then(() => {
        // workaround: it's weird that postion is set while constructing phase will make click event not working
        this.marker.setLngLat(this.point);
        if (this.label === undefined) {
          return;
        }

        this._label = new window.T.Label({
          text: this.label,
          position: this.marker.getLngLat(),
          offset: new window.T.Point(-45, 40)
        });

        this._label.setBackgroundColor('transparent');
        this._label.setBorderLine(0);
        this._label.setFontColor('#FFFFFF');
        this._service.addOverlay((map) => {
          return this._label;
        });
      });
  }

  public ngOnChanges(changes: { [propertyName: string]: SimpleChange }) {

    if (changes.point && !changes.point.isFirstChange()) {
      // this.marker.setPosition(toPoint(changes.point.currentValue))
    }
    /**/
    if (changes.options && !changes.options.isFirstChange()) {
      this.setOptions(changes.options.currentValue);
    }

  }

  public ngOnDestroy() {

    this._service.removeOverlay(this.marker);

    if (this._label !== undefined) {
        this._service.removeOverlay(this._label);
      }

  }

  private setOptions(options: MarkerOptions): void {

    if (isNull(options)) {
        return;
      }
      if (!isNull(options.draggable)) {

        if (options.draggable) {
            this.marker.enableDragging();
        }else{
            this.marker.disableDragging();
        }

        // this.marker.set .setOffset(toSize(options.offset))
      }

  }

  private addListener(marker: Marker, map: TMapInstance) {
    marker.addEventListener('click', (e: any) => {
      this.clicked.emit({
        e,
        map,
        marker
      });
    });


    marker.addEventListener('dragstart', (e: any) => {
      this.dragstarted.emit({
        e,
        map,
        marker
      });
    });

    marker.addEventListener('drag', (e: any) => {
      this._label.setLngLat(marker.getLngLat());
      this.draged.emit({
        e,
        map,
        marker
      });
    });

    marker.addEventListener('dragend', (e: any) => {
      this.dragended.emit({
        e,
        map,
        marker
      });
    });

  }
}
